package discovery

import (
	"encoding/binary"
	"fmt"
	"net"
	"rtps/common"
	"rtps/messages"
	"time"
)

// SEDP端点管理器
type EndpointManager struct {
	Participant   *Participant
	LocalWriters  map[string]*WriterEndpoint
	LocalReaders  map[string]*ReaderEndpoint
	RemoteWriters map[string]*WriterEndpoint
	RemoteReaders map[string]*ReaderEndpoint
}

// Writer端点
type WriterEndpoint struct {
	GUID       common.GUID
	TopicName  string
	TypeName   string
	QoS        QoSProfile
	Locator    common.Locator
	LastUpdate time.Time
}

// Reader端点
type ReaderEndpoint struct {
	GUID       common.GUID
	TopicName  string
	TypeName   string
	QoS        QoSProfile
	Locator    common.Locator
	LastUpdate time.Time
}

// QoS配置
type QoSProfile struct {
	Reliability uint8
	Durability  uint8
	Deadline    time.Duration
}

// 创建新的端点管理器
func NewEndpointManager(participant *Participant) *EndpointManager {
	return &EndpointManager{
		Participant:   participant,
		LocalWriters:  make(map[string]*WriterEndpoint),
		LocalReaders:  make(map[string]*ReaderEndpoint),
		RemoteWriters: make(map[string]*WriterEndpoint),
		RemoteReaders: make(map[string]*ReaderEndpoint),
	}
}

// 注册本地Writer
func (em *EndpointManager) RegisterLocalWriter(topicName, typeName string, qos QoSProfile) (*WriterEndpoint, error) {
	writer := &WriterEndpoint{
		GUID: common.GUID{
			Prefix:   em.Participant.GUIDPrefix,
			EntityID: generateEntityID(0xC2), // Writer实体类型
		},
		TopicName:  topicName,
		TypeName:   typeName,
		QoS:        qos,
		Locator:    em.getDefaultLocator(),
		LastUpdate: time.Now(),
	}

	guidStr := guidToString(writer.GUID)
	em.LocalWriters[guidStr] = writer

	// 发送SEDP发现消息
	if err := em.announceWriter(writer); err != nil {
		delete(em.LocalWriters, guidStr)
		return nil, fmt.Errorf("failed to announce writer: %v", err)
	}

	return writer, nil
}

// 注册本地Reader
func (em *EndpointManager) RegisterLocalReader(topicName, typeName string, qos QoSProfile) (*ReaderEndpoint, error) {
	reader := &ReaderEndpoint{
		GUID: common.GUID{
			Prefix:   em.Participant.GUIDPrefix,
			EntityID: generateEntityID(0xC7), // Reader实体类型
		},
		TopicName:  topicName,
		TypeName:   typeName,
		QoS:        qos,
		Locator:    em.getDefaultLocator(),
		LastUpdate: time.Now(),
	}

	guidStr := guidToString(reader.GUID)
	em.LocalReaders[guidStr] = reader

	// 发送SEDP发现消息
	if err := em.announceReader(reader); err != nil {
		delete(em.LocalReaders, guidStr)
		return nil, fmt.Errorf("failed to announce reader: %v", err)
	}

	return reader, nil
}

// 宣布Writer端点
func (em *EndpointManager) announceWriter(writer *WriterEndpoint) error {
	msg := messages.NewMessage(em.Participant.GUIDPrefix)

	// 添加Data子消息（包含Writer信息）
	dataSubmsg := &messages.Data{
		Header: messages.SubmessageHeader{
			SubmessageID: common.MessageTypeData,
			Flags:        0x01,
		},
		ReaderID: messages.EntityID{
			EntityKey:  [3]byte{0x00, 0x00, 0x03}, // SEDP内置Reader
			EntityKind: 0xC2,
		},
		WriterID: messages.EntityID{
			EntityKey:  [3]byte{0x00, 0x00, 0x04}, // SEDP内置Writer
			EntityKind: 0xC2,
		},
		WriterSN: messages.SequenceNumber{
			High: 0,
			Low:  1,
		},
		SerializedData: em.serializeWriterData(writer),
	}
	msg.AddSubmessage(dataSubmsg)

	// 发送给所有发现的参与者
	participants := em.Participant.GetDiscoveredParticipants()
	for _, participant := range participants {
		addr := &net.UDPAddr{
			IP:   bytesToIP(participant.Locator.Address),
			Port: int(participant.Locator.Port),
		}

		if err := em.Participant.Transport.SendMessage(msg, addr); err != nil {
			fmt.Printf("Failed to send writer announcement to %s: %v\n", addr.String(), err)
		}
	}

	return nil
}

// 宣布Reader端点
func (em *EndpointManager) announceReader(reader *ReaderEndpoint) error {
	msg := messages.NewMessage(em.Participant.GUIDPrefix)

	// 添加Data子消息（包含Reader信息）
	dataSubmsg := &messages.Data{
		Header: messages.SubmessageHeader{
			SubmessageID: common.MessageTypeData,
			Flags:        0x01,
		},
		ReaderID: messages.EntityID{
			EntityKey:  [3]byte{0x00, 0x00, 0x03}, // SEDP内置Reader
			EntityKind: 0xC2,
		},
		WriterID: messages.EntityID{
			EntityKey:  [3]byte{0x00, 0x00, 0x04}, // SEDP内置Writer
			EntityKind: 0xC2,
		},
		WriterSN: messages.SequenceNumber{
			High: 0,
			Low:  1,
		},
		SerializedData: em.serializeReaderData(reader),
	}
	msg.AddSubmessage(dataSubmsg)

	// 发送给所有发现的参与者
	participants := em.Participant.GetDiscoveredParticipants()
	for _, participant := range participants {
		addr := &net.UDPAddr{
			IP:   bytesToIP(participant.Locator.Address),
			Port: int(participant.Locator.Port),
		}

		if err := em.Participant.Transport.SendMessage(msg, addr); err != nil {
			fmt.Printf("Failed to send reader announcement to %s: %v\n", addr.String(), err)
		}
	}

	return nil
}

// 序列化Writer数据
func (em *EndpointManager) serializeWriterData(writer *WriterEndpoint) []byte {
	// 计算数据大小
	topicLen := len(writer.TopicName)
	typeLen := len(writer.TypeName)
	dataSize := 32 + topicLen + typeLen // 固定字段 + 字符串长度

	data := make([]byte, dataSize)
	offset := 0

	// 写入GUID
	copy(data[offset:offset+12], writer.GUID.Prefix[:])
	offset += 12
	copy(data[offset:offset+4], writer.GUID.EntityID[:])
	offset += 4

	// 写入Topic名称长度和内容
	binary.BigEndian.PutUint32(data[offset:offset+4], uint32(topicLen))
	offset += 4
	copy(data[offset:offset+topicLen], []byte(writer.TopicName))
	offset += topicLen

	// 写入Type名称长度和内容
	binary.BigEndian.PutUint32(data[offset:offset+4], uint32(typeLen))
	offset += 4
	copy(data[offset:offset+typeLen], []byte(writer.TypeName))
	offset += typeLen

	// 写入QoS配置
	data[offset] = writer.QoS.Reliability
	offset += 1
	data[offset] = writer.QoS.Durability
	offset += 1
	binary.BigEndian.PutUint64(data[offset:offset+8], uint64(writer.QoS.Deadline))

	return data
}

// 序列化Reader数据
func (em *EndpointManager) serializeReaderData(reader *ReaderEndpoint) []byte {
	// 计算数据大小
	topicLen := len(reader.TopicName)
	typeLen := len(reader.TypeName)
	dataSize := 32 + topicLen + typeLen // 固定字段 + 字符串长度

	data := make([]byte, dataSize)
	offset := 0

	// 写入GUID
	copy(data[offset:offset+12], reader.GUID.Prefix[:])
	offset += 12
	copy(data[offset:offset+4], reader.GUID.EntityID[:])
	offset += 4

	// 写入Topic名称长度和内容
	binary.BigEndian.PutUint32(data[offset:offset+4], uint32(topicLen))
	offset += 4
	copy(data[offset:offset+topicLen], []byte(reader.TopicName))
	offset += topicLen

	// 写入Type名称长度和内容
	binary.BigEndian.PutUint32(data[offset:offset+4], uint32(typeLen))
	offset += 4
	copy(data[offset:offset+typeLen], []byte(reader.TypeName))
	offset += typeLen

	// 写入QoS配置
	data[offset] = reader.QoS.Reliability
	offset += 1
	data[offset] = reader.QoS.Durability
	offset += 1
	binary.BigEndian.PutUint64(data[offset:offset+8], uint64(reader.QoS.Deadline))

	return data
}

// 处理SEDP消息
func (em *EndpointManager) HandleSEDPMessage(msg *messages.Message, addr *net.UDPAddr) {
	for _, submsg := range msg.Submessages {
		switch sm := submsg.(type) {
		case *messages.Data:
			if sm.ReaderID.EntityKind == 0xC2 && sm.WriterID.EntityKind == 0xC2 {
				// 这是SEDP数据消息
				em.handleEndpointData(sm, addr)
			}
		}
	}
}

// 处理端点数据
func (em *EndpointManager) handleEndpointData(data *messages.Data, addr *net.UDPAddr) {
	if len(data.SerializedData) < 32 {
		fmt.Printf("Invalid endpoint data length: %d\n", len(data.SerializedData))
		return
	}

	// 解析端点类型（通过EntityID判断）
	entityKind := data.WriterID.EntityKind
	if entityKind == 0xC2 {
		// Writer端点
		writer := em.parseWriterData(data.SerializedData, addr)
		if writer != nil {
			guidStr := guidToString(writer.GUID)
			em.RemoteWriters[guidStr] = writer
			fmt.Printf("Discovered remote writer: %s for topic %s\n", guidStr, writer.TopicName)
		}
	} else if entityKind == 0xC7 {
		// Reader端点
		reader := em.parseReaderData(data.SerializedData, addr)
		if reader != nil {
			guidStr := guidToString(reader.GUID)
			em.RemoteReaders[guidStr] = reader
			fmt.Printf("Discovered remote reader: %s for topic %s\n", guidStr, reader.TopicName)
		}
	}
}

// 解析Writer数据
func (em *EndpointManager) parseWriterData(data []byte, addr *net.UDPAddr) *WriterEndpoint {
	offset := 0

	// 读取GUID
	var guid common.GUID
	copy(guid.Prefix[:], data[offset:offset+12])
	offset += 12
	copy(guid.EntityID[:], data[offset:offset+4])
	offset += 4

	// 读取Topic名称
	topicLen := int(binary.BigEndian.Uint32(data[offset : offset+4]))
	offset += 4
	if offset+topicLen > len(data) {
		return nil
	}
	topicName := string(data[offset : offset+topicLen])
	offset += topicLen

	// 读取Type名称
	typeLen := int(binary.BigEndian.Uint32(data[offset : offset+4]))
	offset += 4
	if offset+typeLen > len(data) {
		return nil
	}
	typeName := string(data[offset : offset+typeLen])
	offset += typeLen

	// 读取QoS配置
	reliability := data[offset]
	offset += 1
	durability := data[offset]
	offset += 1
	deadline := time.Duration(binary.BigEndian.Uint64(data[offset : offset+8]))

	return &WriterEndpoint{
		GUID:      guid,
		TopicName: topicName,
		TypeName:  typeName,
		QoS: QoSProfile{
			Reliability: reliability,
			Durability:  durability,
			Deadline:    deadline,
		},
		Locator: common.Locator{
			Kind:    1,
			Port:    uint32(addr.Port),
			Address: ipToBytes(addr.IP),
		},
		LastUpdate: time.Now(),
	}
}

// 解析Reader数据
func (em *EndpointManager) parseReaderData(data []byte, addr *net.UDPAddr) *ReaderEndpoint {
	offset := 0

	// 读取GUID
	var guid common.GUID
	copy(guid.Prefix[:], data[offset:offset+12])
	offset += 12
	copy(guid.EntityID[:], data[offset:offset+4])
	offset += 4

	// 读取Topic名称
	topicLen := int(binary.BigEndian.Uint32(data[offset : offset+4]))
	offset += 4
	if offset+topicLen > len(data) {
		return nil
	}
	topicName := string(data[offset : offset+topicLen])
	offset += topicLen

	// 读取Type名称
	typeLen := int(binary.BigEndian.Uint32(data[offset : offset+4]))
	offset += 4
	if offset+typeLen > len(data) {
		return nil
	}
	typeName := string(data[offset : offset+typeLen])
	offset += typeLen

	// 读取QoS配置
	reliability := data[offset]
	offset += 1
	durability := data[offset]
	offset += 1
	deadline := time.Duration(binary.BigEndian.Uint64(data[offset : offset+8]))

	return &ReaderEndpoint{
		GUID:      guid,
		TopicName: topicName,
		TypeName:  typeName,
		QoS: QoSProfile{
			Reliability: reliability,
			Durability:  durability,
			Deadline:    deadline,
		},
		Locator: common.Locator{
			Kind:    1,
			Port:    uint32(addr.Port),
			Address: ipToBytes(addr.IP),
		},
		LastUpdate: time.Now(),
	}
}

// 辅助函数
func generateEntityID(kind uint8) [4]byte {
	var entityID [4]byte
	entityID[3] = kind
	return entityID
}

func guidToString(guid common.GUID) string {
	return fmt.Sprintf("%x%x", guid.Prefix, guid.EntityID)
}

func (em *EndpointManager) getDefaultLocator() common.Locator {
	return common.Locator{
		Kind:    1,
		Port:    common.DefaultPortUser,
		Address: [16]byte{127, 0, 0, 1}, // localhost
	}
}

func bytesToIP(bytes [16]byte) net.IP {
	// 检查是否为IPv4地址（后4字节）
	if bytes[0] == 0 && bytes[1] == 0 && bytes[2] == 0 && bytes[3] == 0 &&
		bytes[4] == 0 && bytes[5] == 0 && bytes[6] == 0 && bytes[7] == 0 &&
		bytes[8] == 0 && bytes[9] == 0 && bytes[10] == 0 && bytes[11] == 0 {
		return net.IPv4(bytes[12], bytes[13], bytes[14], bytes[15])
	}
	return net.IP(bytes[:])
}
